package gghilo

import (
	"github.com/shopspring/decimal"
	"math/rand"
	"wzgames/internal/constant"
	"wzgames/internal/model/gamep"
	"wzgames/internal/model/gkindp"
	"wzgames/internal/model/statement"
	"wzgames/internal/secure/rng"
	"wzgames/internal/secure/rng/cards"
)

type Gift struct {
	total  int
	totalD decimal.Decimal
}

func (gf *Gift) Init(cfg *gkindp.HiLoConfig) {
	gf.total = 52
	gf.totalD = decimal.NewFromInt32(52)
}

func (gf *Gift) Update(cfg *gkindp.HiLoConfig) {

}

func (gf *Gift) ChangeCard() string {
	idx := rand.Int31n(52)
	suiteIdx := idx % 4
	suite := cards.CardSuiteOrder[suiteIdx]
	rankIdx := idx / 4
	rank := cards.CardRankOrder[rankIdx]
	return cards.Card2String(&gamep.Card{Suite: suite, Rank: rank})
}

func (gf *Gift) GetTotal() int {
	return gf.total
}

func (gf *Gift) Calculate(servSeed, clientSeed string, roundNum int) []*gamep.Card {
	nums := rng.CalculateHashWithRound(servSeed, clientSeed, rng.ChunkSize, 16, roundNum)
	var ret []*gamep.Card
	for i := 0; i < 16; i++ {
		card := cards.RandCard(nums[i])
		ret = append(ret, &card)
	}
	//fmt.Println(roundNum, ret)
	return ret
}

func (gf *Gift) CalcNextPayout(card *gamep.Card, preval float64) (string, float64, string, float64) {
	var leftCmpType, rightCmpType string
	var aa, a2 int32
	aa = 0
	a2 = 0
	if card.Rank == gamep.CardRank_TWO {
		leftCmpType = constant.KeySame
		rightCmpType = constant.KeyHigh
		a2 = 1
	} else if card.Rank == gamep.CardRank_ACE {
		leftCmpType = constant.KeyLow
		rightCmpType = constant.KeySame
		aa = 1
	} else {
		leftCmpType = constant.KeyLowOrSame
		rightCmpType = constant.KeyHighOrSame
	}
	u := decimal.NewFromFloat(preval)
	lv := u.Mul(gf.totalD).Div(decimal.NewFromInt32(4 * (int32(card.Rank) - 1 - aa)))
	lf, _ := lv.Float64()
	rv := u.Mul(gf.totalD).Div(gf.totalD.Sub(decimal.NewFromInt32(4 * (int32(card.Rank) - 2 + a2))))
	rf, _ := rv.Float64()
	return leftCmpType, lf, rightCmpType, rf
}

func (gf *Gift) OpenCheck(openPay *gkindp.HiloPay, betQ *statement.HiloBetInfo) (bool, *gamep.Card) {
	count := int(betQ.BetInfo.Save.CardCount)
	if len(betQ.Result) < count {
		betQ.RoundNum += 1
		addRet := gf.Calculate(betQ.BetInfo.Save.ServerSeed, betQ.BetInfo.Save.ClientSeed, betQ.RoundNum)
		betQ.Result = append(betQ.Result, addRet...)
	}
	openCard := betQ.Result[count-1]
	var r bool
	switch openPay.GetCmpType() {
	case constant.KeySame:
		r = openCard.GetRank() == betQ.BetInfo.FlagCard.GetRank()
	case constant.KeyHigh:
		r = openCard.GetRank() > betQ.BetInfo.FlagCard.GetRank()
	case constant.KeyLow:
		r = openCard.GetRank() < betQ.BetInfo.FlagCard.GetRank()
	case constant.KeyLowOrSame:
		r = openCard.GetRank() <= betQ.BetInfo.FlagCard.GetRank()
	case constant.KeyHighOrSame:
		r = openCard.GetRank() >= betQ.BetInfo.FlagCard.GetRank()
	}

	return r, openCard
}
